package ;
import scuts.traits.Traits;

@:build(scuts.traits.Traits.register())
interface Person<T:Float> {
	public var name:T;
	public var age:Int;
	public function new (name:T, age:Int) {
		this.name = name;
		this.age = age;
	}
	
}

class MyPerson implements Person<Int> {}



@:build(scuts.traits.Traits.register())
interface PrintablePerson<T:Float> implements Person<T> {
	public function printMe ():Void {
		trace("name: " + name + " - age: " + age);
	}
}


@:build(scuts.traits.Traits.register())
interface DrawablePerson<T,S:Float> implements Person<S> {
	public function drawMe (with :T):Void {
		
		trace("name: " + name + " - age: " + age);
		trace(with );
	}
}


interface DrawablePersonString implements DrawablePerson<String, Float> {}


class SpecialPerson implements PrintablePerson<Float> {
	
}

class SpecialPerson2 implements PrintablePerson<Float>, implements DrawablePerson<Int, Float> { }


@:build(scuts.traits.Traits.register())
interface MyTrait {
	public function blub ():Void {
		trace("MyTrait::blub");
	}
}


@:build(scuts.traits.Traits.register())
interface EventDispatcher {
	
	private var listeners:Array < Void->Void > ;
	
	public function dispatch ():Void {
		for (l in listeners.iterator()) {
			l();
		}
	}
	
	public function addListener (l:Void->Void):Void {
		if (listeners == null) listeners = [];
		listeners.push(l);
	}
	
}


@:build(scuts.traits.Traits.register())
interface Dispatcher {
	
	public function dispatch ():Void {
		for (l in listeners) {
			l();
		}
	}
	
}



@:build(scuts.traits.Traits.register())
interface Dispatcher2 {
	
	public function dispatch ():Void {
		trace("DISPATCHER2");
		for (l in listeners) {
			l();
		}
	}
	
}


class Game implements EventDispatcher, implements Dispatcher {
	private var listeners:List<Void->Void> ;
	public function new () { }
	public function addListener (l:Void->Void):Void {
		if (listeners == null) listeners = new List();
		listeners.push(l);
	}
	
	public function dispatch ():Void {
		for (l in listeners) {
			l();
		}
	}
}

class Game2 extends Game, implements Dispatcher2{
	
	public function new () { 
		super();
	}
	
	override public function dispatch ():Void {
		for (l in listeners) {
			l();
		}
	}
	
}


@:build(scuts.traits.Traits.register())
class MyTraitClass {
	
	public function blub ():Void {
		trace("MyTraitClass::blub");
	}
}

class MyTraitImplementor implements MyTrait {
	public function new () {}
}


class MyTraitClassImplementor  extends MyTraitClass {
	public function new () {}
}

class MyTraitClassImplementor2 extends MyTraitClass {
	public function new () { }
	override public function blub ():Void {
		trace("MyTraitClassImplementor2::blub");
	}
}


class Foo extends MyTraitClassImplementor2 {
	
	override public function blub ():Void {
		trace("Foo::blub");
	}
	
	
}



class Main
{
	static function main () {
		//var imp = new MyTraitImplementor();
		//imp.blub();
		//var g = new Game();
		//g.addListener(function () trace("called"));
		//g.dispatch();
		
		var x = new SpecialPerson(1.1, 18);
		x.printMe();
		var x2 = new SpecialPerson2(2.1, 18);
		x2.drawMe(1);
		//var d:DrawablePerson = x;
		
		var m = new MyPerson(3, 18);
		m.age;
		
		
		
		
		
		
		
		
		
	}
	
}
